package dper.study.codes.concurrent.model;

import org.apache.log4j.Logger;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by leichen on 2017/3/21.
 */
public class ProConBufferLockAndCondition  implements ProConBuffer{
    Logger logger = Logger.getLogger(ProConBufferLockAndCondition.class) ;

    private int bufferLen = 10 ;

    private LinkedList<Integer> buffer = new LinkedList<Integer>() ;

    private Lock lock = new ReentrantLock() ;
    private Lock lock_fair = new ReentrantLock(true) ;

    /**
     * Condition更强大的地方在于：能够更加精细的控制多线程的休眠与唤醒。对于同一个锁，可以创建多个Condition，在不同的情况下使用不同的Condition。
     */
    private Condition notFull = lock_fair.newCondition() ;
    private Condition notEmpty = lock_fair.newCondition() ;

    public  void set(int i){
        lock_fair.lock();
        try {
            while (buffer.size()==bufferLen){
                notFull.await();
            }
            buffer.add(i) ;
            logger.info(Thread.currentThread()+"\tproducer add "+i+" in buffer\tNow size " + buffer.size());
            notEmpty.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            lock_fair.unlock();
        }

    }
    public int get() throws InterruptedException {
        lock_fair.lock();
        try {
            while (buffer.size()==0){
                notEmpty.await();
            }
            int head = buffer.poll() ;
            logger.info(Thread.currentThread()+"\tconsumer consume "+ head+" from buffer\tNow size " + buffer.size() );
            notFull.signalAll();
            return head ;
        }finally {
            lock_fair.unlock();
        }
    }
}
